﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Rage
{
    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class TalentDataAttribute : Attribute
    {
        public TalentDataAttribute(int index, string name, int maxPoints, int tree, int column, int row, int prerequisite, string[] description, string icon)
        {
            _index = index;
            _name = name;
            _maxPoints = maxPoints;
            _tree = tree;
            _column = column;
            _row = row;
            _prerequisite = prerequisite;
            _description = description;
            _icon = icon;
        }

        private readonly int _index;
        private readonly string _name;
        private readonly int _maxPoints;
        private readonly int _tree;
        private readonly int _column;
        private readonly int _row;
        private readonly int _prerequisite;
        private readonly string _icon;
        private readonly string[] _description;

        public int Index { get { return _index; } }
        public string Name { get { return _name; } }
        public int MaxPoints { get { return _maxPoints; } }
        public int Tree { get { return _tree; } }
        public int Column { get { return _column; } }
        public int Row { get { return _row; } }
        public int Prerequisite { get { return _prerequisite; } }
        public string[] Description { get { return _description; } }
        public string Icon { get { return _icon; } }

        public override string ToString()
        {
            return string.Format("Index{0:00} T{1} R{2} C{3} P{4:00} M{5} {6}",
                Index, Tree, Row, Column, Prerequisite, MaxPoints, Name);
        }
    }

    public abstract class TalentsBase
    {
        public abstract int[] Data { get; }
        //
        public virtual int TreeStartingIndexes_0 { get { return 0; } }
        public virtual int TreeStartingIndexes_1 { get { return 0; } }
        public virtual int TreeStartingIndexes_2 { get { return 0; } }
        public int[] TreeStartingIndexes { get { return new int[] { TreeStartingIndexes_0, TreeStartingIndexes_1, TreeStartingIndexes_2 }; } }
        public int[] TreeLengths
        {
            get
            {
                return new int[] {
                    TreeStartingIndexes_1,
                    TreeStartingIndexes_2 - TreeStartingIndexes_1,
                    Data.Length - TreeStartingIndexes_2,
                };
            }
        }
        public int[] treeCounts = { -1, -1, -1 };
        //
        public int[] TreeCounts
        {
            get
            {
                if (treeCounts[0] == -1)
                {
                    treeCounts[0] = 0;
                    for (int i = TreeStartingIndexes[0]; i < TreeStartingIndexes[1]; i++)
                    {
                        treeCounts[0] += Data[i];
                    }
                }
                if (treeCounts[1] == -1)
                {
                    treeCounts[1] = 0;
                    for (int i = TreeStartingIndexes[1]; i < TreeStartingIndexes[2]; i++)
                    {
                        treeCounts[1] += Data[i];
                    }
                }
                if (treeCounts[2] == -1)
                {
                    treeCounts[2] = 0;
                    for (int i = TreeStartingIndexes[2]; i < Data.Length; i++)
                    {
                        treeCounts[2] += Data[i];
                    }
                }
                return treeCounts;
            }
            protected set { treeCounts = value; }
        }
        //
        public int HighestTree
        {
            get
            {
                int[] trees = TreeCounts;
                if (trees[0] >= trees[1] && trees[0] >= trees[2]) { return 0; }
                if (trees[1] >= trees[0] && trees[1] >= trees[2]) { return 1; }
                if (trees[2] >= trees[0] && trees[2] >= trees[1]) { return 2; }
                return 0;
            }
        }
        //
        protected void LoadString(string code)
        {
            if (string.IsNullOrEmpty(code)) return;
            int[] _data = Data;
            string talents = code;
            if (talents.Length >= _data.Length)
            {
                List<int> data = new List<int>();
                foreach (Char digit in talents)
                    data.Add(int.Parse(digit.ToString()));
                data.CopyTo(0, _data, 0, _data.Length);
            }
        }
        //
        public override string ToString()
        {
            StringBuilder ret = new StringBuilder();
            foreach (int digit in Data)
                ret.Append(digit.ToString());
            return ret.ToString();
        }

        public CharacterClass GetClass()
        {
            // Imperial
            if (GetType() == typeof(JuggernautTalents)) return CharacterClass.Juggernaut;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Marauder;
            if (GetType() == typeof(AssassinTalents)) return CharacterClass.Assassin;
            if (GetType() == typeof(SorcererTalents)) return CharacterClass.Sorcerer;
            if (GetType() == typeof(PowertechTalents)) return CharacterClass.Powertech;
            if (GetType() == typeof(MercenaryTalents)) return CharacterClass.Mercenary;
            if (GetType() == typeof(OperativeTalents)) return CharacterClass.Operative;
            if (GetType() == typeof(SniperTalents)) return CharacterClass.Sniper;
            // Republic
            if (GetType() == typeof(GuardianTalents)) return CharacterClass.Guardian;
            if (GetType() == typeof(SentinelTalents)) return CharacterClass.Sentinel;
            if (GetType() == typeof(ShadowTalents)) return CharacterClass.Shadow;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Sage;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Marauder;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Marauder;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Marauder;
            if (GetType() == typeof(MarauderTalents)) return CharacterClass.Marauder;
            //
            return CharacterClass.Juggernaut;
        }

        public abstract TalentsBase Clone();
    }
}
